﻿using System;

namespace ForgeCraft
{
    public class PlayerInventory : Window
    {
        private Player _Player;

        public PlayerInventory(Player player)
            : base(0, "Inventory")
        {
            _Player = player;
            ID = 0;
            slots = new InventoryItem[45];
            for (int i = 0; i < slots.Length; ++i)
            {
                slots[i].Type = -1;
            }
            _Viewers.Add(_Player);
        }

        override public void Open(Player player) { /* nil */ }

        override public void Close(Player player)
        {
            //TODO: Discard Items
            InventoryItem clearItem = new InventoryItem();
            clearItem.Clear();

            for (int i = 0; i < 5; i++)
            {
                if (slots[i].Type != -1)
                {
                    if (!AddItem(slots[i]))
                    {
                        BlockPosition spawnPos = player.GetFacingCoord();
                        new PickupEntity(spawnPos.x, spawnPos.y, spawnPos.z, slots[i], player.currentWorld, new Velocity(0, 0, 0));
                        
                    }
                    SetSlot((short)i, clearItem);
                }
            }

            player.info.InventorySave(player);
        }

        public void DiscardObject(Player player, short slot)
        {
            InventoryItem tempItem = slots[slot];

            if (slots[slot].Type < 1) return;

            SetSlot(slot, PopItem(slots[slot]));

            tempItem.Count = 1;

            BlockPosition spawnPos = player.GetFacingCoord();
            new PickupEntity(spawnPos.x, spawnPos.y, spawnPos.z, tempItem, player.currentWorld, new Velocity(5372, 1343, 5372));
        }

        override public bool Click(Player p, short slot, byte type, InventoryItem item)
        {
            Pair<bool, InventoryItem> TryAddResult;
            InventoryItem holding = p.WindowHolding;
            InventoryItem tempItem = holding;
            tempItem.Clear();

            if (slot < 0) // outside window
            {
                if (type == 1)
                {
                    p.WindowHolding.Count = 1; //TODO: This doesn't look right...

                    if (p.WindowHolding.Count == 1)
                    {
                        p.WindowHolding.Clear();
                    }
                    else
                    {
                        holding.Count--;
                        if (!item.Equals(slots[slot])) return false;
                        p.SetHolding(slots[slot]);
                        SetSlot(slot, item);
                    }

                    tempItem = holding;
                    tempItem.Count = 1;
                    
                    BlockPosition spawnPos = p.GetFacingCoord();
                    new PickupEntity(spawnPos.x, spawnPos.y, spawnPos.z, tempItem, p.currentWorld, new Velocity(5372, 0, 5372));
                }
                else
                {
                    p.WindowHolding.Clear();

                    BlockPosition spawnPos = p.GetFacingCoord();
                    new PickupEntity(spawnPos.x, spawnPos.y, spawnPos.z, holding, p.currentWorld, new Velocity(5372, 0, 5372));
                }
                return true;
            }
            else if (slot == 0)
            {
                if (holding.Type > 0) //Player has removed something from craft slot
                {
                    if (!holding.Type.Equals(item.Type)) return false;
                    else if (holding.Count > 63) return false;
                    else
                    {
                        for (short i = 1; i < 5; i++) //Decrement craft slots
                        {
                            SetSlot(i, PopItem(slots[i]));
                        }

                        holding.Count += item.Count;
                        p.SetHolding(holding);
                        return true;
                    }
                }
                else //Player wants to take something from crafted slot
                {
                    if (item.Type > 1)
                    {
                        for (short i = 1; i < 5; i++) //Decrement craft slots
                        {
                            SetSlot(i, PopItem(slots[i]));
                        }

                        if (!holding.Type.Equals(item.Type))
                        {
                            p.SetHolding(item);
                            //SetSlot(slot, holding);
                        }
                        else //Player already is holding an item
                        {
                            if (holding.Count > 63) return false;

                            holding.Count++;
                            SetSlot(slot, PopItem(item, item.Count));
                            p.SetHolding(holding);
                        }
                    }
                    else
                    {
                        p.SetHolding(item); 
                    }
                }
                return true;
            }
            else
            {
                if (holding.Type > 0) //Held item Click
                {
                    if (type == 0) //Normal click
                    {
                        if (!holding.Type.Equals(slots[slot].Type))
                        {
                            p.SetHolding(slots[slot]);
                            SetSlot(slot, holding);
                            return true;
                        }
                        TryAddResult = TryAddItem(slot, holding);
                        if (TryAddResult.First)
                        {
                            holding.Clear();
                            p.SetHolding(holding);
                        }
                        else
                        {
                            p.SetHolding(TryAddResult.Second);
                        }
                    }
                    else //Player has right-clicked
                    {
                        if (!holding.Type.Equals(slots[slot].Type) && slots[slot].Type > 0)
                        {
                            p.SetHolding(slots[slot]);
                            SetSlot(slot, holding);
                            return true;
                        }
                        InventoryItem singleItem = holding;

                        singleItem.Count = 1;

                        TryAddResult = TryAddItem(slot, singleItem);

                        if (TryAddResult.First)
                        {
                            p.SetHolding(PopItem(holding));
                        }
                        else
                        {
                            p.SetHolding(TryAddResult.Second);
                        }
                    }
                    return true;
                }
                else //Unheld Inv Click
                {
                    if (type == 0) //Normal click
                    {
                        if (item.Equals(slots[slot]))
                        {
                            p.SetHolding(slots[slot]);
                            SetSlot(slot, holding);
                        }
                        else //Set them down in a slot
                        {
                            if (!holding.Equals(slots[slot])) return false;
                            TryAddResult = TryAddItem(slot, item);
                            if (TryAddResult.First)
                            {
                                holding.Clear();
                                p.SetHolding(holding);
                            }
                            else
                            {
                                p.SetHolding(TryAddResult.Second);
                            }
                        }
                    }
                    else //Player has right-clicked
                    {
                        //if (item.Type > 0) //Player has split a stack.
                        if (item.Count > 1)
                        {
                            int items = Math.Abs(item.Count / 2);
                            int remainder = Math.Abs(item.Count % 2);

                            tempItem = item;
                            item.Count = (byte)items;
                            tempItem.Count = (byte)(items + remainder);
                            SetSlot(slot, item);
                            p.SetHolding(tempItem);
                        }
                        else
                        {
                            p.SetHolding(item);
                            item.Clear();
                            SetSlot(slot, item);
                        }
                    }
                    return true;
                }
            }
        }

        public void PopItemSlot(short slot)
        {
            //TODO: This probably has an issue with sticks being 4. (Yeah, there is, but it ain't too serious)
            //..But does it? This removes an item, so why would 4 be an issue??? 
            if (slots[slot].Type > 0)
            {
                if (slots[slot].Count == 1)
                {
                    slots[slot].Clear();
                }
                else
                {
                    slots[slot].Count -= 1;
                }
            }
        }

        public void DamageItemSlot(short slot)
        {
            short durability = 0;

            Items.ToolDuarability.TryGetValue((Item)slots[slot].Type, out durability);

            if (durability > 0) //Item doesn't decay.
            {
                if (slots[slot].Damage == durability)
                {
                    if (slots[slot].Count == 1)
                    {
                       slots[slot].Clear();
                    }
                    else
                    {
                        slots[slot].Damage = 0;
                        slots[slot].Count--;
                    }
                }
                else
                {
                    slots[slot].Damage++;
                }
            }

        }

         public bool AddItem(InventoryItem item)
        {
            // TODO: Better logic.
            for (short i = 36; i < 45; ++i)
            {
                if (TryAddItem(i, item).First) return true;
            }
            for (short i = 9; i < 36; ++i)
            {
                if (TryAddItem(i, item).First) return true;
            }

            return false;
        }
    }
}
